package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {

	defer func() {
		if errMsg := recover(); errMsg != nil {
			fmt.Println(errMsg)
		}
	}()

	// io.Copy  将数据拷贝
	str := strings.NewReader("Hello, This Is Io Copy \n")
	if _, err := io.Copy(os.Stdout, str); err != nil { // 将字符串内容转接(拷贝)到 Linux标准输出
		panic(err)
	}

	// io.CopyBuffer  和io.Copy相同, 不过使用了缓冲区, 而不是使用临时缓冲区
	str2 := strings.NewReader("Hello, This Is Io CopyBuffer \n")
	str3 := strings.NewReader("Hello, This Is Io CopyBuffer Second \n")
	buf := make([]byte, 16) // buf的长度不能为0, 否则会引发 panic
	if _, err := io.CopyBuffer(os.Stdout, str2, buf); err != nil {
		panic(err)
	}
	if _, err := io.CopyBuffer(os.Stdout, str3, buf); err != nil { // 重复使用之前的缓冲区, 而不需要再次分配新的缓冲区
		panic(err)
	}

	// io.CopyN  用于限制Copy的长度(字节)
	str4 := strings.NewReader("Hello, This Is Io CopyN \n")
	if _, err := io.CopyN(os.Stdout, str4, 5); err != nil {
		panic(err)
	}

	// io.Pipe  数据流管道, 可以在goroutine中使用 write 写入数据, 在主进程读取
	read, write := io.Pipe()
	go func() {
		_, _= fmt.Fprint(write, "This Is Goroutine Msg \n") // 将数据写入 io.Pipe 的写入端, Fprint 将数据输出到指定的数据输出(如os.Stdout等)
		_ = write.Close()
	}()
	buf2 := new(bytes.Buffer) // 创建一块字节缓冲区
	_, _ = buf2.ReadFrom(read)       // 从 io.Pipe 的读取端取得 goroutine写入的数据
	fmt.Println(buf2.String())

	// io.ReadAtLeast  指定最少读取数, 如果读取到结束达不到指定的最小长度, 则会出现err, 如果buf区的大小小于最小读取数, 则会引发错误
	str5 := strings.NewReader("Hello, This Is Io.ReadAtLeast \n")
	buf3 := make([]byte, 10)
	if _, err := io.ReadAtLeast(str5, buf3, 6); err != nil {
		panic(err)
	}
	fmt.Println(string(buf3))

	// io.ReadFull  读取 len(buf) 长度的字符串到 buf4 缓冲区, 直到填满整个缓冲区
	str6 := strings.NewReader("Hello, This Is Io ReadFull \n")
	buf4 := make([]byte, 26)
	if _, err := io.ReadFull(str6, buf4); err != nil {
		panic(err)
	}
	fmt.Println(string(buf4))

	// io.WriteString  将指定的字符串数据写入
	_, _ = io.WriteString(os.Stdout, "Hello, This Is Io WriteString \n")
}
